#pragma once
#include "exchangeClass.hpp"
#include "QueueData.hpp"
#include "QueueMessageManage.hpp"
#include "BindInfo.hpp"
#include <memory>

namespace MY_MQ{
    class VirtualHost{
        

        public:
        VirtualHost(const std::string &HostName,const std::string &BaseDir,
                    const std::string& DBFilePath
        )
        :_host_name(HostName)
        ,_ExchangeManagerPtr(std::make_shared<ExchangeManager>(DBFilePath))
        ,_QueueManagerPtr(std::make_shared<QueueManager>(DBFilePath))
        ,_BindInfoManagerPtr(std::make_shared<BindInfoManager>(DBFilePath))
        ,_MessageQueueManagerPtr(std::make_shared<MessageQueueManager> (BaseDir))
        {
            
        }
        bool DeclareExchange(const std::string & ExchangeName,MQ_Protobuf::ExchangeType EType,bool durable,bool autoDelete,const google::protobuf::Map<std::string,std::string> &args)
        {
            return _ExchangeManagerPtr->declareExchange(ExchangeName,EType,durable,autoDelete,MY_MQ::Serialization_Util::serializeMap(args));
        }
        bool DeleteExchange(const std::string & ExchangeName)
        {
            return _ExchangeManagerPtr->removeExchange(ExchangeName);
        }
        bool ExsitExchange(const std::string& ExchangeName)
        {
            return _ExchangeManagerPtr->exsits(ExchangeName);
        }
        Exchange::_self_ptr selectExchange(const std::string & ExchangeName)
        {
            return _ExchangeManagerPtr->SelectExchange(ExchangeName);
        }
        bool DeclareQueue(const std::string & QueueName,bool durable,bool Exclusive,bool autoDelete,const google::protobuf::Map<std::string,std::string> &args)
        {
            _MessageQueueManagerPtr->initQueueMessage(QueueName);
            return _QueueManagerPtr->DeclareQueue(QueueName,durable,Exclusive,autoDelete,MY_MQ::Serialization_Util::serializeMap(args));
        }
        void DeleteQueue(const std::string & QueueName)
        {
            _MessageQueueManagerPtr->destroyQueueMessage(QueueName);
            _BindInfoManagerPtr->RemoveQueueBindings(QueueName);
            _QueueManagerPtr->DeleteQueue(QueueName);
        }
        bool ExsitQueue(const std::string& QueueName)
        {
            return _QueueManagerPtr->exist(QueueName);
        }
        QueueManager::QueueMap AllQueues()
        {
            return _QueueManagerPtr-> GetAllQueueData();
        }


        bool Bind(const std::string &ExchangeName,const std::string &QueueName,const std::string& Key)
        {
            Exchange::_self_ptr ExchangePtr = _ExchangeManagerPtr->SelectExchange(ExchangeName);
            if(ExchangePtr == nullptr)
            {
                logw("Bind Queue to ExchangeHost false, Cause:ExchangeName is not exist");
                return false;
            }
            QueueData::self_ptr QueuePtr = _QueueManagerPtr->SelectQueueData(QueueName);
            if(QueuePtr == nullptr)
            {
                logw("Bind Queue to ExchangeHost false, Cause:QueueName is not exist");
                return false;
            }
            return _BindInfoManagerPtr->Bind(ExchangePtr->_name,QueuePtr->_name,Key,QueuePtr->_durable && ExchangePtr->_durable);
        }
        bool UnBind(const std::string &ExchangeName,const std::string &QueueName)
        {
            return _BindInfoManagerPtr->Unbind(ExchangeName,QueueName);
        }

        MsgQueue_BindingMap ExchangeBindMap(const std::string exchange_name)
        {
            return  _BindInfoManagerPtr->GetQueueBindingMap(exchange_name);
        }

        bool ExsitBinding(const std::string &ExchangeName,const std::string & QueueName)
        {
            return _BindInfoManagerPtr->exist(ExchangeName,QueueName);
        }

        bool BasicPublish(const std::string &queuename,const MQ_Protobuf::BasicProperties bp,const std::string& body)
        {
            QueueData::self_ptr QPtr = _QueueManagerPtr->SelectQueueData(queuename);
            if(QPtr.get() == nullptr)
            {
                loge("发布消息失败，队列{}不存在!",queuename);
                return false;
            }
            return _MessageQueueManagerPtr->insert(queuename,bp,body,QPtr->_durable);
        }
        bool BasicPublish(const std::string &queuename,const std::string& body)
        {
            QueueData::self_ptr QPtr = _QueueManagerPtr->SelectQueueData(queuename);
            if(QPtr.get() == nullptr)
            {
                loge("发布消息失败，队列{}不存在!",queuename);
                return false;
            }
            return _MessageQueueManagerPtr->insert(queuename,body,QPtr->_durable);
        }
        MessagePtr BasicConsum(const std::string& queuename)
        {
            return _MessageQueueManagerPtr->front(queuename);
        }

        void BasicAck(const std::string &qname,const std::string & msgId)
        {
            return _MessageQueueManagerPtr->Confirm(qname,msgId);
        }
        void clear()
        {
            _ExchangeManagerPtr ->clear();
            _QueueManagerPtr ->clear();
            _BindInfoManagerPtr ->clear();
            _MessageQueueManagerPtr ->clear();
        }
        using self_ptr = std::shared_ptr<VirtualHost>;
        private:
        std::string _host_name;
        ExchangeManager::self_ptr _ExchangeManagerPtr;
        QueueManager::self_ptr _QueueManagerPtr;
        BindInfoManager::self_ptr _BindInfoManagerPtr;
        MessageQueueManager::self_ptr _MessageQueueManagerPtr;
    };
};